package cn.tedu.em.user.webapi.service.impl;

import cn.tedu.em.common.exception.EstateManagementServiceException;
import cn.tedu.em.common.pojo.user.dto.UserAddNewDTO;
import cn.tedu.em.common.pojo.user.dto.UserLoginDTO;
import cn.tedu.em.common.pojo.user.dto.UserUpdateDTO;
import cn.tedu.em.common.pojo.user.entity.User;
import cn.tedu.em.common.pojo.user.vo.UserItemForAdminVO;
import cn.tedu.em.common.pojo.user.vo.UserItemForUserVO;
import cn.tedu.em.common.pojo.user.vo.UserListForAdminVO;
import cn.tedu.em.common.restful.ResponseCode;
import cn.tedu.em.user.service.IUserService;
import cn.tedu.em.user.webapi.mapper.UserMapper;
import cn.tedu.em.user.webapi.security.UserDetails;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class UserService implements IUserService {

    @Value("${em.jwt.secret-key}")
    private String secretKey;
    @Value("${em.jwt.duration-in-minute}")
    private Long durationInMinute;

    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    UserMapper userMapper;
    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public String loginUser(UserLoginDTO userLoginDTO) {
        log.debug("开始处理【管理员登录】的业务, 参数: {}",userLoginDTO);
        Authentication authentication = new UsernamePasswordAuthenticationToken(
                userLoginDTO.getUsername(),userLoginDTO.getPassword()
        );
        Authentication authenticateResult = authenticationManager.authenticate(authentication);
        log.debug("认证通过!(如果未通过,过程中抛出异常,你不会看到此条日志!)");
        log.debug("认证结果: {}", authenticateResult);
        log.debug("认证结果中的当事人: {}", authenticateResult.getPrincipal());

        UserDetails userDetails = (UserDetails) authenticateResult.getPrincipal();
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", userDetails.getId());
        claims.put("username", userDetails.getUsername());
        String authoritiesJsonString = JSON.toJSONString(userDetails.getAuthorities());
        claims.put("authoritiesJsonString", authoritiesJsonString);

        String jwt = Jwts.builder()
                //Header: 声明算法与Token类型
                .setHeaderParam("alg","HS256")
                .setHeaderParam("typ","JWT")
                // Payload：数据，具体表现为Claims
                .setClaims(claims)
                .setExpiration(new Date(System.currentTimeMillis() + durationInMinute * 60 * 1000))
                // Verify Signature：验证签名
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .compact();
        log.debug("生成了JWT数据: {}", jwt);
        return jwt;
    }

    @Override
    public void addNew(UserAddNewDTO userAddNewDTO) {
        log.debug("开始处理【添加用户】的业务,参数:{}", userAddNewDTO);
        String username = userAddNewDTO.getUsername();
        int count = userMapper.countByUsername(username);
        if (count > 0){
            String message = "添加用户失败,用户名已存在!";
            log.warn(message);
            throw new EstateManagementServiceException(
                    ResponseCode.CONFLICT, message);
        }
        User user = new User();
        BeanUtils.copyProperties(userAddNewDTO, user);
        String phone = userAddNewDTO.getPhone();
        String password = phone.substring(phone.length() - 6);
        String encodedPassword = passwordEncoder.encode(password);
        user.setPassword(encodedPassword);
        int rows = userMapper.insert(user);
        if (rows != 1){
            String message = "新增用户失败，服务器忙，请稍后再尝试！";
            log.warn(message);
            throw new EstateManagementServiceException(
                    ResponseCode.INTERNAL_SERVER_ERROR, message);
        }
    }

    @Override
    public void deleteById(Long id) {
        log.debug("开始处理【删除用户】的业务,参数:{}", id);
        UserItemForAdminVO user = userMapper.getUserItemForAdminById(id);
        if (user == null){
            String message = "删除用户失败,尝试删除的用户数据不存在!";
            log.warn(message);
            throw new EstateManagementServiceException(
                    ResponseCode.NOT_FOUND, message);
        }
        int rows = userMapper.deleteById(id);
        if (rows != 1){
            String message = "删除用户失败，服务器忙，请稍后再尝试！";
            log.warn(message);
            throw new EstateManagementServiceException(
                    ResponseCode.INTERNAL_SERVER_ERROR, message);
        }
    }

    @Override
    public void updateById(UserUpdateDTO userUpdateDTO) {
        log.debug("开始处理【修改用户信息】的业务,参数:{}", userUpdateDTO);
        int count = userMapper.countByUsernameAndNotId(userUpdateDTO.getUsername(), userUpdateDTO.getId());
        if (count > 0){
            String message = "修改用户信息失败,用户名已被占用!";
            log.warn(message);
            throw new EstateManagementServiceException(
                    ResponseCode.CONFLICT, message);
        }
        log.debug("dto:{}",userUpdateDTO);
        User user = new User();
        BeanUtils.copyProperties(userUpdateDTO, user);
        log.debug("user:{}",user);
        int rows = userMapper.updateById(user);
        if (rows != 1){
            String message = "修改用户信息失败，服务器忙，请稍后再尝试！";
            log.warn(message);
            throw new EstateManagementServiceException(
                    ResponseCode.INTERNAL_SERVER_ERROR, message);
        }
    }

    @Override
    public UserItemForUserVO getUserItemForUserById(Long id) {
        log.debug("开始处理【根据id查询用户详情返回给用户】的业务,参数:{}", id);
        UserItemForUserVO userItemForUser = userMapper.getUserItemForUserById(id);

        return userItemForUser;
    }

    @Override
    public UserItemForAdminVO getUserItemForAdminById(Long id) {
        log.debug("开始处理【根据id查询用户详情返回给管理员】的业务,参数:{}", id);
        UserItemForAdminVO userItemForAdmin = userMapper.getUserItemForAdminById(id);

        return userItemForAdmin;
    }

    @Override
    public List<UserListForAdminVO> getUserList() {
        log.debug("开始处理【查询用户列表】的业务");
        List<UserListForAdminVO> userList = userMapper.getUserList();
        return userList;
    }
}
